package com.ruoyi.common.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.ruoyi.common.scoket.PutObjectProgressListener;
import com.ruoyi.common.utils.file.FileUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * Oss服务调用
 */
@Log4j2
@Component
public class OssUtil {

    /**
     * Endpoint 存储对象概述  阿里云主账号AccessKey，accessKeySecret拥有所有API的访问权限  访问路径前缀  存储对象概述
     */
//    https://oss-cn-beijing.aliyuncs.com
    @Value("${alibaba.cloud.oss.endpoint}")
    private  String endPointConfig;
    private static String endPoint ;
    private static String accessKeyId = "LTAI5tQxBbtZ3yxC2FYSjTbA";
    private static String accessKeySecret = "md2YXFHvOT26NoByeInQN9mZGdLkBS";
    private static String accessPre = "https://bridgebj.oss-cn-beijing.aliyuncs.com/";



    @PostConstruct
    public void setCoordinationProt() {
        System.out.println(this.endPointConfig);
       endPoint = this.endPointConfig;

        ossClient = new OSSClientBuilder().build(
                endPoint,
                accessKeyId,
                accessKeySecret);
        log.info("oss服务连接成功！");
    }


    /**
     * bucket名称
     *
     * @return
     */
    private static String bucketName = "bridgebj";

    private static OSS ossClient;

//    static {
//        ossClient = new OSSClientBuilder().build(
//                endPoint,
//                accessKeyId,
//                accessKeySecret);
//        log.info("oss服务连接成功！");
//    }

    /**
     * 默认路径上传本地文件
     *
     * @param filePath
     */
    public static String uploadFile(String filePath) {
        return uploadFileForBucket(bucketName, getOssFilePath(filePath), filePath);
    }

    /**
     * 默认路径上传multipartFile文件
     *
     * @param multipartFile
     */
    public static String uploadMultipartFile(MultipartFile multipartFile) {
        return uploadMultipartFile(bucketName, getOssFilePath(multipartFile.getOriginalFilename()), multipartFile);
    }

    /**
     * 上传 multipartFile 类型文件
     *
     * @param bucketName
     * @param ossPath
     * @param multipartFile
     */
    public static String uploadMultipartFile(String bucketName, String ossPath, MultipartFile multipartFile) {
        InputStream inputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        uploadFileInputStreamForBucket(bucketName, ossPath, inputStream);
        return accessPre + ossPath;
    }

    /**
     * 使用File上传PutObject上传文件 ** 程序默认使用次方法上传
     *
     * @param bucketName 实例名称
     * @param ossPath    oss存储路径
     * @param filePath   本地文件路径
     */
    public static String uploadFileForBucket(String bucketName, String ossPath, String filePath) {
        // 创建PutObjectRequest对象。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossPath, new File(filePath));

        // 上传
        ossClient.putObject(putObjectRequest);
        return accessPre + ossPath;
    }

    /**
     * 使用文件流上传到指定的bucket实例
     *
     * @param bucketName 实例名称
     * @param ossPath    oss存储路径
     * @param filePath   本地文件路径
     */
    public static String uploadFileInputStreamForBucket(String bucketName, String ossPath, String filePath) {

        // 填写本地文件的完整路径。如果未指定本地路径，则默认从示例程序所属项目对应本地路径中上传文件流。
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(filePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。
        uploadFileInputStreamForBucket(bucketName, ossPath, inputStream);
        return accessPre + ossPath;
    }

    public static void uploadFileInputStreamForBucket(String bucketName, String ossPath, InputStream inputStream) {
        ossClient.putObject(bucketName, ossPath, inputStream);
    }

    /**
     * 使用网络地址上传到指定的bucket实例
     */
    public static String uploadImageFromUrl(String url) {
        String ossPath ="";
        // 通过图片的url创建输入流
        try (InputStream inputStream = new URL(url).openStream()) {
            URL urlPath = new URL(url);
            String path = urlPath.getPath();
            ossPath =  getOssFilePath(path.substring(path.lastIndexOf('/') + 1));
            log.info(ossPath);
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossPath,inputStream);
            // 上传
            ossClient.putObject(putObjectRequest);
        } catch (IOException e) {
            log.info("文件不存在,检查读取路径",e);
        }
//        finally {
//            ossClient.shutdown();
//        }
        log.info(accessPre + ossPath);
        return accessPre + ossPath;
    }

    /**
     * 下载
     *
     * @param ossFilePath
     * @param filePath
     */
    public static void downloadFile(String ossFilePath, String filePath) {
        downloadFileForBucket(bucketName, ossFilePath, filePath);
    }

    /**
     * 下载
     *
     * @param bucketName  实例名称
     * @param ossFilePath oss存储路径
     * @param filePath    本地文件路径
     */
    public static void downloadFileForBucket(String bucketName, String ossFilePath, String filePath) {
        ossClient.getObject(new GetObjectRequest(bucketName, ossFilePath), new File(filePath));
    }

    public static void fileDownload(String url, HttpServletResponse response) throws MalformedURLException {


        URL urlS = new URL(url);
        String path = urlS.getPath();
        String realFileName = path.substring(path.lastIndexOf("/")+1);
        String fileName = url.replace("https://bridgebj.oss-cn-beijing.aliyuncs.com/","");

        InputStream cosObjectInput = null;
        try {
            OSSObject cosObject = ossClient.getObject(bucketName,fileName);
            //文件流
            cosObjectInput = cosObject.getObjectContent();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 处理下载到的流
        // 这里是直接读取，按实际情况来处理
        byte[] bytes = null;
        try {
            bytes = IOUtils.toByteArray(cosObjectInput);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            response.getOutputStream().write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 用完流之后一定要调用 close()
            try {
                cosObjectInput.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //在流没有处理完之前，不能关闭 cosClient
        // 确认本进程不再使用 cosClient 实例之后，关闭之
//        cosClient.shutdown();
    }

    public static void deleteOssFile(String fileName) throws Exception{
        // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
//        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
//        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称，例如examplebucket。
//        String bucketName = "examplebucket";
        // 填写文件完整路径。文件完整路径中不能包含Bucket名称。
        // 创建OSSClient实例。
//        OSS ossClient = new OSSClientBuilder().build(endPoint, credentialsProvider);
        try {
            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, fileName);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            log.error(fileName+"删除失败！"+oe.getErrorMessage());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
            log.error(fileName+"删除失败！"+ce.getErrorMessage());
        } finally {
//            if (ossClient != null) {
//                ossClient.shutdown();
//            }
        }
    }

    /**
     * @return
     */
    public static String getOssDefaultPath() {
        LocalDateTime now = LocalDateTime.now();
        //图片路径更新为
        String url =
                "pic" + "/";
//        String url =
//                "public" + "/" +
//                        now.getYear() + "/" +
//                        now.getMonth() + "/" +
//                        now.getDayOfMonth() + "/" +
//                        now.getHour() + "/" +
//                        now.getMinute() + "/";
        return url;
    }

    public static String getOssFilePath(String filePath) {
        String fileSuf = filePath.substring(filePath.indexOf(".") + 1);
        String fileName = filePath.substring(0,filePath.indexOf("."));
//        return getOssDefaultPath() + UUID.randomUUID().toString() + "." + fileSuf;
        Long timeStr = System.currentTimeMillis();
        System.out.println(getOssDefaultPath()+ timeStr.toString() +"_" + fileName+ "." + fileSuf);
        return getOssDefaultPath()+ timeStr.toString() +"_" + fileName+ "." + fileSuf;
    }

    public static void main(String[] args) {
        System.out.println(UUID.randomUUID().toString());
        Long timeStr = System.currentTimeMillis() / 1000;
        String ss = timeStr.toString();
        System.out.println(ss);
//        System.out.println(System.currentTimeMillis() / 1000);
    }

    /**
     * 文件上传并监听进度
     * @param file，requestId，session
     * @return {@link String }
     * @author yangz
     * @date 2023/10/11
     */
    public static String uploadFile(MultipartFile file, String requestId, WebSocketSession session) throws IOException {
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        // 获取文件大小
        long fileSize = file.getSize();
        String originalFilename = getOssFilePath(file.getOriginalFilename());

        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, originalFilename, file.getInputStream());
        // 文件上传请求附加监听器
        putObjectRequest.withProgressListener(new PutObjectProgressListener(session,fileSize));
        ossClient.putObject(putObjectRequest);
        ossClient.shutdown();
        return accessPre + originalFilename;
    }
}
